package test

/**
 * @author: Yardena
 * @date: Oct 13, 2009 4:26:26 PM
 */

import scala.reflect.Manifest
import htmap.HTMap;

object Test4 {

  abstract class Alias[S,T](s:S,f:(S=>T)) extends (()=>T) {
    type Method
    final def apply = f(s)
    def convert: Method
  }
  class Eligible[S,T](val function: S=>T) extends (S=>T) {
    def apply(s:S) = { function(s) }
    def as[M](t:(T => M)) = { s:S =>
      (new Alias(s,function) {type Method = M;  override def convert = t(function(s))}).convert
    }
  }
  implicit def lift[S,T](f: S=>T) = new Eligible(f)
//  implicit def convert[M<:MethodWrapper](m:M):M#Method = m.convert

  def merge[A1,A2](a1:A1, a2:A2)(implicit m1:Manifest[A1],m2:Manifest[A2]) = {
    //(a1,a2).asInstanceOf[A1 with A2] //TODO real thing
    HTMap().+(a1)(m1).+(a2)(m2)
  }
  class Base[S](val subject:S) {
    def select[X](project:(S=>X))(implicit m1:Manifest[X]) = HTMap().+(project(subject))(m1)
    def select[X,Y](project1:(S=>X), project2:(S=>Y))(implicit m1:Manifest[X],m2:Manifest[Y]) = {
      merge(project1(subject),project2(subject))(m1,m2)
    }
  }
  def from[S](s: S):Base[S] = new Base(s)

  def alias[S,T,M](f:(S=>T),m:T=>M)(s:S):M = {
    (new Alias[S,T](s,f){ type Method = M; override def convert = m(f(s)) }).convert
  }

  class Column[T](val value:T)
  def column[T](implicit m:Manifest[T]) = { map:HTMap[T] => map./[T](m) }
  def value[V,T<:Column[V]](implicit m:Manifest[T]) = { map:HTMap[T] => column[T](m)(map).value }

  case class BD(i:Int) extends Column(i)
  case class DD(i:Int) extends Column(i)

  def main(args : Array[String]) {
    val x = HTMap(new BD(1953),new DD(2003))
    case class Birthday(i:Int) extends Column(i)
    val test = from(x).select(column[DD], value[Int,BD].as(new Birthday(_)))
    val test2 = from(test).select(column[DD])
    println(test./[Birthday].value)
    println(test./[DD].value)
    ;
  }
}
